package com.xxl.sso.core.filter;

import com.xxl.sso.core.conf.Conf;
import com.xxl.sso.core.login.SsoWebLoginHelper;
import com.xxl.sso.core.path.impl.AntPathMatcher;
import com.xxl.sso.core.user.XxlSsoUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * web sso filter
 *
 * @author xuxueli 2018-04-03
 */
public class XxlSsoWebFilter extends HttpServlet implements Filter {
    private static Logger logger = LoggerFactory.getLogger(XxlSsoWebFilter.class);

    private static final AntPathMatcher antPathMatcher = new AntPathMatcher();

    private String ssoServer;
    private String logoutPath;
    private String excludedPaths;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        logger.info("XxlSsoWebFilter init. filter常量配置---start");

        //获取配置中的常量：
        ssoServer = filterConfig.getInitParameter(Conf.SSO_SERVER);             // http://xxlssoserver.com:8080/xxl-sso-server
        logoutPath = filterConfig.getInitParameter(Conf.SSO_LOGOUT_PATH);       // /logout
        excludedPaths = filterConfig.getInitParameter(Conf.SSO_EXCLUDED_PATHS); // null

        logger.info("XxlSsoWebFilter init. filter常量配置---end");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;

        // make url
        String servletPath = req.getServletPath();

        // 排除项 excluded path check
        if (excludedPaths != null && excludedPaths.trim().length() > 0) {
            for (String excludedPath : excludedPaths.split(",")) {
                String uriPattern = excludedPath.trim();

                // 支持ANT表达式
                if (antPathMatcher.match(uriPattern, servletPath)) {
                    // excluded path, allow
                    chain.doFilter(request, response);
                    return;
                }

            }
        }

        //登出 logout path check
        if (logoutPath != null
                && logoutPath.trim().length() > 0
                && logoutPath.equals(servletPath)) {

            // remove cookie
            SsoWebLoginHelper.removeSessionIdByCookie(req, res);

            // redirect logout   "http://xxlssoserver.com:8080/xxl-sso-server".concat("/logout");
            String logoutPageUrl = ssoServer.concat(Conf.SSO_LOGOUT);
            res.sendRedirect(logoutPageUrl);

            return;
        }

        // valid login user, cookie + redirect   check共享session中是否 存在user
        XxlSsoUser xxlUser = SsoWebLoginHelper.loginCheck(req, res);

        // valid login fail  使得客户端的login直接会先 重定向到server端的login方法
        if (xxlUser == null) {

            String header = req.getHeader("content-type");
            boolean isJson = header != null && header.contains("json");
            if (isJson) {

                // json msg
                res.setContentType("application/json;charset=utf-8");
                res.getWriter().println("{\"code\":" + Conf.SSO_LOGIN_FAIL_RESULT.getCode() + ", \"msg\":\"" + Conf.SSO_LOGIN_FAIL_RESULT.getMsg() + "\"}");
                return;
            } else {

                // total link
                String link = req.getRequestURL().toString();

                //通过url 把client中的login拦截到 server中的login 校验
                // redirect logout   "http://xxlssoserver.com:8080/xxl-sso-server".concat("/login");
                String loginPageUrl = ssoServer.concat(Conf.SSO_LOGIN)
                        + "?" + Conf.REDIRECT_URL + "=" + link;   // xxlssoserver.com需要配置host白名单
                // http://xxlssoserver.com:8080/xxl-sso-server/login?redirect_url=http://localhost:8081/xxl-sso-web-sample-springboot/
                res.sendRedirect(loginPageUrl);
                return;
            }

        }

        //共享session存在该用户的session数据  证明已经经过了sso登录认证，则直接获取该用户，直接走到客户端的主界面
        // ser sso user
        request.setAttribute(Conf.SSO_USER, xxlUser);

        // already login, allow  此处的意思就是：共享session中数据已存在了！已经login过sso的server了！可直接到达client端主界面
        chain.doFilter(request, response);// 将请求转发给 过滤器链 的下一个filter，没有下一个filter，则回退到被当前filter拦截的那个url接口
        return;
    }

}
